package eval

import (
	"showen/lex"
	"showen/obj"
	"showen/parse"
	"testing"
)

func TestIOIntegration(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{
		{
			input:    "(input-port? (current-input-port))",
			expected: "#t",
		},
		{
			input:    "(output-port? (current-output-port))",
			expected: "#t",
		},
		{
			input:    "(input-port? (current-output-port))",
			expected: "#f",
		},
		{
			input:    "(output-port? (current-input-port))",
			expected: "#f",
		},
		{
			input:    "(char-ready?)",
			expected: "#t",
		},
	}

	env := obj.NewEnvironment()
	RegisterBuiltinProcedures(env)

	for _, tt := range tests {
		t.Run(tt.input, func(t *testing.T) {
			lexer := lex.NewLexer(tt.input)
			tokens := lexer.ReadTokens()

			parser := parse.NewParser(tokens)
			expr, err := parser.ParseExpression()
			if err != nil {
				t.Fatalf("ParseExpression() error = %v", err)
			}

			result, err := EvalExpression(expr, env)
			if err != nil {
				t.Fatalf("EvalExpression() error = %v", err)
			}

			if result.Inspect() != tt.expected {
				t.Errorf("For input %q, expected %q, got %q", tt.input, tt.expected, result.Inspect())
			}
		})
	}
}

func TestTranscriptIntegration(t *testing.T) {
	tests := []struct {
		input    string
		expected string
	}{
		{
			input:    `(transcript-on "test_transcript_integration.txt")`,
			expected: "",
		},
		{
			input:    "42",
			expected: "42",
		},
		{
			input:    `(transcript-off)`,
			expected: "",
		},
	}

	env := obj.NewEnvironment()
	RegisterBuiltinProcedures(env)

	for _, tt := range tests {
		t.Run(tt.input, func(t *testing.T) {
			lexer := lex.NewLexer(tt.input)
			tokens := lexer.ReadTokens()

			parser := parse.NewParser(tokens)
			expr, err := parser.ParseExpression()
			if err != nil {
				t.Fatalf("ParseExpression() error = %v", err)
			}

			result, err := EvalExpression(expr, env)
			if err != nil {
				t.Fatalf("EvalExpression() error = %v", err)
			}

			// For transcript functions, we expect NULL_OBJECT which has empty Inspect() result
			if result.Inspect() != tt.expected {
				t.Errorf("For input %q, expected %q, got %q", tt.input, tt.expected, result.Inspect())
			}
		})
	}

	// Clean up test file
	// os.Remove("test_transcript_integration.txt")
}
